package com.zego.wawaji.socket;

import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;

import com.alibaba.fastjson.JSON;
import com.zego.wawaji.base.module.ModuleMgr;
import com.zego.wawaji.socket.utils.IMUtils;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

/**
 * socket消息发送结构体
 */
public class NetData implements Parcelable {
    private long uid = 0;       // 中4个字节存储用于识别客户端的ID，是一个无符号整数
    private String content = "";
    private int msgType = -1;       // 消息类型：如 MSG_ID_HEART_BEAT3
    private long messageId = -1;    // 消息id，对应消息体中的"d"字段，不存在消息id则为-1
    private long fromId = -1;       // 消息发送者id，不存在fid则为-1
    private long tuid = -1;         // 消息接受者id，不存在则为-1

    private String msgBody = "";    // 最终拼接供传输的JSON消息体

    /**
     * 登录，心跳数据包
     */
    public NetData() {
        Map<String, Object> loginMap = new HashMap<>();
        loginMap.put("Id", ModuleMgr.getLoginMgr().getUid());
        loginMap.put("Auth", ModuleMgr.getLoginMgr().getAuth());
        loginMap.put("Imei", ModuleMgr.getAppMgr().getIMEI());
        msgBody = JSON.toJSONString(loginMap);
    }

    /**
     * 接收到的消息数据体
     */
    public NetData(String msgBody) {
        this.msgBody = msgBody;
    }

    /**
     * 发送普通消息数据包:  TCP , Http都需要创建NetData
     */
    public NetData(long uid, int msgType, String content) {
        super();
        this.uid = uid;
        this.msgType = msgType;
        this.content = content;
    }

    /**
     * 从数据流中解析并读取数据体
     */
    public static NetData parseNetData(InputStream inputStream) throws IOException {
        NetData netData = null;
        String msgBody = "";    // 接收到的消息体
        String line = "";

        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));
        StringBuffer buffer = new StringBuffer();

        try {
            // 服务器给的每条回复消息以回车符结尾，所以读到一条数据后直接break掉while循环
            while ((line = in.readLine()) != null) {
                buffer.append(line);
                break;
            }
            msgBody = buffer.toString();
        } finally {
//            in.close();
        }

        IMUtils.log("Socket read packet thread packet content:" + msgBody);
        netData = new NetData(msgBody);
        return netData;
    }

    /**
     * Socket传输消息体
     */
    public byte[] getBytes() {
        byte[] ret = null;
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            baos.write(msgBody.getBytes("UTF-8")); // 内容体写入流

            // 添加回车, 服务器做结束校验
            baos.write("\n".getBytes("UTF-8"));
            baos.flush();
            baos.close();
            ret = baos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (OutOfMemoryError ooe) {
            ooe.printStackTrace();
        }
        return ret;
    }

    /**
     * 消息id:  解析返回消息体，不存在返回-1
     */
    public Long getMessageId() {
        if (messageId == -1 && !TextUtils.isEmpty(msgBody)) {
            try {
                JSONObject contentJ = new JSONObject(msgBody);
                messageId = contentJ.optLong("d", -1);
            } catch (JSONException e) {
            }
        }
        return messageId;
    }

    /**
     * 重置或添加消息Id，仅对已加密过得数据体使用
     * 如：已使用以下构造方法后使用
     * public NetData(long uid, int msgType, String content)
     */
    public void setMessageId(long msgId) {
        if (msgId == -1 || TextUtils.isEmpty(msgBody)) return;
        try {
            JSONObject contentJ = new JSONObject(msgBody);
            contentJ.put("d", msgId);
            content = contentJ.toString();
            this.messageId = msgId;
        } catch (JSONException e) {
        }
    }

    /**
     * 发送者id:  不存在消息体或不存在发送者则返回-1
     * <p>
     * 10000: 表示系统发送
     */
    public Long getFromId() {
        if (fromId == -1 && !TextUtils.isEmpty(msgBody)) {
            try {
                JSONObject contentJ = new JSONObject(msgBody);
                fromId = contentJ.optLong("UidFrom", -1);
            } catch (JSONException e) {
            }
        }
        return fromId;
    }

    public void setFromId(long fromId) {
        this.fromId = fromId;
    }

    /**
     * 接收者id:  不存在消息体或不存在接收者则返回-1
     */
    public long getTuid() {
        if (tuid == -1 && !TextUtils.isEmpty(msgBody)) {
            try {
                JSONObject contentJ = new JSONObject(msgBody);
                tuid = contentJ.optLong("UidTo", -1);
            } catch (JSONException e) {
            }
        }
        return tuid;
    }

    /**
     * 消息类型
     */
    public int getMsgType() {
        if (msgType == -1 && !TextUtils.isEmpty(msgBody)) {
            try {
                JSONObject contentJ = new JSONObject(msgBody);
                msgType = contentJ.optInt("MsgType", -1);
            } catch (JSONException e) {
            }
        }
        return msgType;
    }

    /**
     * 消息内容
     */
    public String getContent() {
        if (TextUtils.isEmpty(content) && !TextUtils.isEmpty(msgBody)) {
            try {
                JSONObject contentJ = new JSONObject(msgBody);
                content = contentJ.optString("Content", "");
            } catch (JSONException e) {
            }
        }
        return content;
    }

    /**
     * 整个消息体
     */
    public String getMsgBody() {
        return msgBody;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeLong(this.uid);
        dest.writeString(this.content);
        dest.writeInt(this.msgType);
        dest.writeLong(this.messageId);
        dest.writeLong(this.fromId);
        dest.writeLong(this.tuid);
        dest.writeString(this.msgBody);
    }

    protected NetData(Parcel in) {
        this.uid = in.readLong();
        this.content = in.readString();
        this.msgType = in.readInt();
        this.messageId = in.readLong();
        this.fromId = in.readLong();
        this.tuid = in.readLong();
        this.msgBody = in.readString();
    }

    public static final Creator<NetData> CREATOR = new Creator<NetData>() {
        @Override
        public NetData createFromParcel(Parcel source) {
            return new NetData(source);
        }

        @Override
        public NetData[] newArray(int size) {
            return new NetData[size];
        }
    };

    @Override
    public String toString() {
        return "NetData{" +
                "uid=" + uid +
                ", content='" + content + '\'' +
                ", msgType=" + msgType +
                ", messageId=" + messageId +
                ", fromId=" + fromId +
                ", tuid=" + tuid +
                ", msgBody='" + msgBody + '\'' +
                '}';
    }
}
